# coding:utf-8

from gevent import monkey
monkey.patch_all()

import multiprocessing

import common_env    # 请勿删除

from common.marketing_sms_consumer import MarketingSmsConsumer
from common.rabbitmq import RabbitMQ
from common.winner_consumer import DemandWinnerConsumer, AssignRedPacketConsumer
from common.im_client_consumer import IMClientConsumer


class ConsumerServer(object):
    """
    created by chenhj at 2017/7/25
    消息队列
    """
    def __init__(self):
        """
        created by chenhj at 2017/7/25

        """
        self.workers = []

    @staticmethod
    def ignore_exception(callback):
        """
        create by ld_wu 2017-02-08
        忽略消费者处理函数的异常错误,保证消息系统正常运行,
        当出现异常时,系统会记录错误log信息
        """

        def wrapper(*args, **kwargs):
            try:
                return callback(*args, **kwargs)
            except Exception as e:
                # add by ld_wu 2017-02-08
                # TODO write log
                print('Message push failed with error: {}'.format(e))

        return wrapper

    def consume(self, queue, callback, durable, exchange_type=''):
        """
        created by chenhj at 2017/7/25
        当exchange_type为空是, queue表示队列名, 否则表示交换器名
        """
        channel = RabbitMQ().get_channel()
        if not exchange_type:
            channel.queue_declare(queue=queue, durable=durable)
            queue_name = queue
        else:
            channel.exchange_declare(exchange=queue, exchange_type=exchange_type, durable=durable)
            queue_name = channel.queue_declare(exclusive=True).method.queue
            channel.queue_bind(exchange=queue, queue=queue_name)
        channel.basic_qos(prefetch_count=1)
        channel.basic_consume(self.ignore_exception(callback), queue=queue_name, no_ack=True)
        channel.start_consuming()

    def register(self, queue, callback, worker_num, durable=False, exchange_type=''):
        """
        created by chenhj at 2017/7/25
        @:param queue: 队列名
        @:param callback: 回调方法对象
        @:param worker_num: 此消费者所需进程数
        @:param durable: 持久化
        """
        for i in range(worker_num):
            self.workers.append(multiprocessing.Process(
                target=self.consume,
                kwargs={
                    'queue': queue, 'callback': callback, 'durable': durable, 'exchange_type': exchange_type
                }
            ))

    def start_server(self):
        """
        created by chenhj at 2017/7/25

        """
        for worker in self.workers:
            print('[*] server running...')
            worker.start()


if __name__ == '__main__':
    server = ConsumerServer()

    from common.consumer import (
        SmsConsumer, MultiSmsConsumer, CaptchaSmsConsumer,
        ImConsumer, WPHSmsConsumer, ALLIANCESmsConsumer,
        IMMsgConsumer, SyncUserInfoConsumer, WarZoneStatConsumer,
        WarZonePeopleStatConsumer, WarZoneDispatchStatConsumer,
        SevenMoorAudioUploadConsumer, WechatUserConsumer,
        CommonApiConsumer, WPHMultiSmsConsumer,
    )
    from common.wx_consumer import WechatConsumer
    from common.constant import (
        SMS_QUEUE, MULTI_SMS_QUEUE, WECHAT_QUEUE, CAPTCHA_QUEUE, IM_QUEUE,
        WPH_SMS_QUEUE, IM_MESSAGE, SYNC_USER_QUEUE,
        ZONE_STAT_EXCHANGE, SEVEN_MOOR_AUDIO_UPLOAD_QUEUE,
        DEMAND_WINNER_QUEUE, WECHAT_USER_QUEUE,
        IM_CLIENT_QUEUE, MARKETING_DEMAND_SMS_QUEUE,
        COMMON_API_QUEUE, WPH_MULTI_SMS_QUEUE,
        ASSIGN_RED_PACKET_QUEUE, ALLIANCE_SMS_QUEUE
    )
    server.register(SMS_QUEUE, SmsConsumer.msg_callback, 2)
    server.register(WPH_SMS_QUEUE, WPHSmsConsumer.msg_callback, 1)
    server.register(ALLIANCE_SMS_QUEUE, ALLIANCESmsConsumer.msg_callback, 1)
    server.register(MULTI_SMS_QUEUE, MultiSmsConsumer.msg_callback, 2)
    server.register(WECHAT_QUEUE, WechatConsumer.msg_callback, 2)
    server.register(CAPTCHA_QUEUE, CaptchaSmsConsumer.msg_callback, 2)
    server.register(IM_QUEUE, ImConsumer.msg_callback, 2)
    server.register(IM_MESSAGE, IMMsgConsumer.msg_callback, 1)
    server.register(SYNC_USER_QUEUE, SyncUserInfoConsumer.msg_callback, 1)
    server.register(ZONE_STAT_EXCHANGE, WarZoneStatConsumer.msg_callback, 1, exchange_type='fanout')
    server.register(ZONE_STAT_EXCHANGE, WarZonePeopleStatConsumer.msg_callback, 1, exchange_type='fanout')
    server.register(ZONE_STAT_EXCHANGE, WarZoneDispatchStatConsumer.msg_callback, 1, exchange_type='fanout')
    server.register(SEVEN_MOOR_AUDIO_UPLOAD_QUEUE, SevenMoorAudioUploadConsumer.msg_callback, 1)
    server.register(DEMAND_WINNER_QUEUE, DemandWinnerConsumer.msg_callback, 1)
    server.register(WECHAT_USER_QUEUE, WechatUserConsumer.msg_callback, 1)
    server.register(IM_CLIENT_QUEUE, IMClientConsumer.msg_callback, 1)
    server.register(MARKETING_DEMAND_SMS_QUEUE, MarketingSmsConsumer.msg_callback, 1)
    server.register(COMMON_API_QUEUE, CommonApiConsumer.msg_callback, 2)
    server.register(WPH_MULTI_SMS_QUEUE, WPHMultiSmsConsumer.msg_callback, 1)
    server.register(ASSIGN_RED_PACKET_QUEUE, AssignRedPacketConsumer.msg_callback, 1)

    server.start_server()
